//
// Created by 19281121-赵路路@BJTU on 2021/9/17.
//
#pragma once

#include <iostream>
#include <string>

using namespace std;

string Encryption(string str, int a, int b);

string Decryption(string str, int a, int b);

int eGCD(int a, int b);

void Affine() {
    // Preparations
    string plainText;
    string cipherText;
    string decryptedText;
    int a, b;

    // Inputs
    cout << "Please enter the string you want to encrypt:" << endl;
    cin >> plainText;
    cout << "Please enter two integers as a and b:" << endl;
    cin >> a >> b;

    //Encrypt
    cipherText = Encryption(plainText, a, b);
    cout << "The ciphertext is: " << cipherText << endl;

    //Decrypt
    decryptedText = Decryption(cipherText, a, b);
    cout << "The decryptedtext is: " << decryptedText << endl;
}

string Encryption(string str, int a, int b) {
    for (char &i : str) {
        i = ((i - 'a') * a + b) % 26 + 'a';
    }
    return str;
}

string Decryption(string str, int a, int b) {
    int aa = eGCD(26, a);
    for (char &i : str) {
        i = i - 'a';
        if (i < b) {
            i = i + 26;
        }
        i = i - b;
        i = i * aa % 26 + 'a';
    }
    return str;
}

int eGCD(int a, int b) {
    int x[3] = {1, 0, a};
    int y[3] = {0, 1, b};
    int t[3] = {0, 0, 0};
    int q = 0;
    bool flag = true;
    while (flag) {
        q = x[2] / y[2];
        for (int i = 0; i < 3; i++) {
            t[i] = x[i] - q * y[i];
            x[i] = y[i];
            y[i] = t[i];
        }
        if (y[2] == 1) {
            if (y[1] < 0) {
                y[1] += a;
            }
            return y[1];
        }
        if (y[2] == 0) {
            flag = false;
        }
    }
    return 0;
}